package com.ctrip.ec.api.mobile.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.config.WxMaInMemoryConfig;
import com.aliyuncs.exceptions.ClientException;
import com.ctrip.ec.api.mobile.aop.AuthLogin;
import com.ctrip.ec.api.mobile.common.*;
import com.ctrip.ec.api.mobile.model.GenInviteCodeModel;
import com.ctrip.ec.api.mobile.model.MiniappLoginModel;
import com.ctrip.ec.api.mobile.model.MobileLoginModel;
import com.ctrip.ec.api.mobile.model.WechatLoginModel;
import com.ctrip.ec.api.mobile.model.member.StatisticModel;
import com.ctrip.ec.biz.dao.agent.AgentDao;
import com.ctrip.ec.biz.dao.invite.InviteCodeDao;
import com.ctrip.ec.biz.dao.member.MemberDao;
import com.ctrip.ec.biz.dao.member.MemberOauthDao;
import com.ctrip.ec.biz.dao.order.OrderDao;
import com.ctrip.ec.biz.dao.order.OrderGoodsDao;
import com.ctrip.ec.biz.dao.sms.SmsLoginDao;
import com.ctrip.ec.biz.entity.agent.AgentEntity;
import com.ctrip.ec.biz.entity.invite.InviteCodeEntity;
import com.ctrip.ec.biz.entity.member.MemberEntity;
import com.ctrip.ec.biz.entity.member.MemberOauthEntity;
import com.ctrip.ec.biz.entity.member.MemberSession;
import com.ctrip.ec.biz.entity.member.MemberType;
import com.ctrip.ec.biz.entity.sms.SmsLoginEntity;
import com.ctrip.ec.biz.util.RequestUtil;
import com.ctrip.ec.biz.util.SerialCodeGen;
import com.ctrip.ec.biz.util.SmsUtil;
import com.ctrip.ec.dal.PagerSetting;
import com.google.common.base.Strings;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.bouncycastle.cert.ocsp.Req;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;

/**
 * Created by jiangzy on 2018/9/3.
 */
@RestController
@RequestMapping("member")
public class MemberController {

    @Autowired
    private MemberDao member;

    @Autowired
    private SmsLoginDao smsLogin;

    @Autowired
    private MemberOauthDao memberOauth;


    @Autowired
    private OrderGoodsDao orderGoods;

    @Autowired
    private OrderDao order;

    @Autowired
    private InviteCodeDao inviteCode;

    @Autowired
    private AgentDao agent;

    @Value("${imageDomain}")
    private String imageDomain;

    private final static Logger logger = LoggerFactory.getLogger(MemberController.class);

    @PostMapping("loginByMobile")
    public MemberEntity loginByMobile(@RequestBody MobileLoginModel model, HttpServletRequest request) throws Exception {

        if (model.getMobile().equals("17717349806")) {
            MemberEntity entity = member.entityByMobile(model.getMobile());
            return entity;
        }

        SmsLoginEntity entity = smsLogin.entityByMobile(model.getMobile());
        if (entity == null) {
            throw new ValidateException("未发现该手机验证码信息");
        }

        if (entity.getInUse()) {
            throw new ValidateException("该验证码已被使用");
        }

        if (!entity.getCode().equals(model.getCode())) {
            throw new ValidateException("验证码不对");
        }

        MemberEntity memberEntity = member.entityByMobile(entity.getMobile());

        if (memberEntity == null) {
            memberEntity = new MemberEntity();
            memberEntity.setMobile(entity.getMobile());
            memberEntity.setLevel(0);
            member.save(memberEntity);
            insertInviteCode(memberEntity.getId());
        }

        entity.setInUse(true);
        smsLogin.save(entity);

//        String token = RequestContext.generateToken(memberEntity.getId(), RequestUtil.getClientIp(request), memberEntity.getLevel());

        String token = UUID.randomUUID().toString().replaceAll("-", "");
        memberEntity.setAuthToken(token);
        memberEntity.setLastLogin(new Timestamp(System.currentTimeMillis()));
        memberEntity.setLastIp(RequestUtil.getClientIp(request));
        member.save(memberEntity);

        member.refreshSession(memberEntity);


        return memberEntity;

    }


    private void insertInviteCode(Long memberId) throws SQLException {

        for (int i = 0; i < 99; i++) {
            InviteCodeEntity inviteCodeEntity = new InviteCodeEntity();
            inviteCodeEntity.setInUse(false);
            //inviteCodeEtity.setCode()
            inviteCodeEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
            inviteCodeEntity.setMemberId(memberId);
            inviteCode.save(inviteCodeEntity);
            inviteCodeEntity.setCode(SerialCodeGen.toSerialCode(inviteCodeEntity.getId(), 6));
            inviteCode.save(inviteCodeEntity);
        }
    }

    @GetMapping("test")
    public String test() {
        logger.info("hello test");
        return "hello";
    }

    @PostMapping("loginByWechat")
    public MemberEntity loginByWechat(@RequestBody WechatLoginModel model, HttpServletRequest request) throws Exception {
        if (Strings.isNullOrEmpty(model.getOpenId())) {
            throw new ValidateException("openId不能为空");
        }
        MemberOauthEntity memberOauthEntity = memberOauth.entityByOpenId(model.getOpenId());
        MemberEntity memberEntity;
        if (memberOauthEntity == null) { //第一次登录需要绑手机
            memberOauthEntity = new MemberOauthEntity();
            //entity.setMemberId(memberEntity.getId());
            memberOauthEntity.setOauth("wechat");
            memberOauthEntity.setOpenId(model.getOpenId());
            memberOauthEntity.setUnionId(model.getUnionId());
            memberOauth.save(memberOauthEntity);
            return null;
        } else {
            memberEntity = member.entity(memberOauthEntity.getMemberId());
            if (memberEntity == null) {
                return null;//需要绑手机
                // throw new ValidateException("用户" + memberOauthEntity.getMemberId() + "缺失");
            }
            String token = UUID.randomUUID().toString().replaceAll("-", "");
            memberEntity.setAuthToken(token);
            memberEntity.setLastLogin(new Timestamp(System.currentTimeMillis()));
            memberEntity.setLastIp(RequestUtil.getClientIp(request));
            member.refreshSession(memberEntity);
            member.save(memberEntity);
            return memberEntity;
        }

    }

    @PostMapping("bindMobile")
    public MemberEntity bindMobile(@RequestBody WechatLoginModel model, HttpServletRequest request) throws Exception {
        if (Strings.isNullOrEmpty(model.getMobile())) {
            throw new ValidateException("请输入手机号");
        }
        SmsLoginEntity smsLoginEntity = smsLogin.entityByMobile(model.getMobile());
        if (smsLoginEntity == null) {
            throw new ValidateException("未发现该手机验证码信息");
        }

        if (smsLoginEntity.getInUse()) {
            throw new ValidateException("该验证码已被使用");
        }

        if (!smsLoginEntity.getCode().equals(model.getCode())) {
            throw new ValidateException("验证码不对");
        }

        MemberOauthEntity entity = memberOauth.entityByOpenId(model.getOpenId());
        MemberEntity memberEntity;
        if (entity != null) {
            //查看手机号有没有注册过
            memberEntity = member.entityByMobile(model.getMobile());
            if (memberEntity == null) {
                memberEntity = new MemberEntity();
                if(!Strings.isNullOrEmpty(model.getNickname())) {
                    memberEntity.setNickname(model.getNickname());
                }else{
                    memberEntity.setNickname(model.getMobile());
                }
                memberEntity.setLevel(0);
                memberEntity.setMobile(model.getMobile());
                member.save(memberEntity);
                insertInviteCode(memberEntity.getId());
            }

            String token = UUID.randomUUID().toString().replaceAll("-", "");
            memberEntity.setAuthToken(token);
            memberEntity.setLastLogin(new Timestamp(System.currentTimeMillis()));
            memberEntity.setLastIp(RequestUtil.getClientIp(request));

            member.save(memberEntity);
            member.refreshSession(memberEntity);

            entity.setMemberId(memberEntity.getId());
            memberOauth.save(entity);
            return memberEntity;
        } else {
            return null;
        }
    }

    @PostMapping("loginByMiniapp")
    public MemberEntity loginByMiniapp(@RequestBody MiniappLoginModel model, HttpServletRequest request) throws SQLException, WxErrorException {
        if (Strings.isNullOrEmpty(model.getAppId())) {
            throw new ValidateException("缺少appId");
        }
        AgentEntity agentEntity = agent.entityByAppId(model.getAppId());

        WxMaInMemoryConfig config = new WxMaInMemoryConfig();
        config.setAppid(agentEntity.getAppId());
        config.setSecret(agentEntity.getAppSecret());
//        config.setToken(this.properties.getToken());
//        config.setAesKey(this.properties.getAesKey());
        config.setMsgDataFormat("JSON");
        WxMaService wxService = new WxMaServiceImpl();
        wxService.setWxMaConfig(config);

        WxMaJscode2SessionResult wxResult = wxService.getUserService().getSessionInfo(model.getCode());
        String openId = wxResult.getOpenid();
        String sessionKey = wxResult.getSessionKey();
        String unionid = wxResult.getUnionid();
        if (sessionKey != null && !sessionKey.isEmpty()) {
            MemberOauthEntity memberOauthEntity = memberOauth.entityByOpenId(openId);
            MemberEntity memberEntity = null;
            if (memberOauthEntity == null) {
                memberEntity = new MemberEntity();
                String encryptedData = request.getHeader("X-WX-Encrypted-Data");
                String iv = request.getHeader("X-WX-IV");
//                WxMaUserInfo wxMaUserInfo = wxService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
//                if (wxMaUserInfo != null) {
//                    //  gender = wxMaUserInfo.getGender() == "男" ? 0 : 1;
//                    memberEntity.setGender(wxMaUserInfo.getGender() == "男");
//                    memberEntity.setNickname(wxMaUserInfo.getNickName());
////                    avatarUrl = wxMaUserInfo.getAvatarUrl();
////                    nickName = wxMaUserInfo.getNickName();
//                }
                memberEntity.setLevel(0);
                memberEntity.setType(MemberType.Miniapp.ordinal());
                memberEntity.setAgentId(agentEntity.getId());
                this.member.save(memberEntity);

                memberOauthEntity = new MemberOauthEntity();
                memberOauthEntity.setOauth("miniapp");
                memberOauthEntity.setOpenId(openId);
                memberOauthEntity.setUnionId(unionid);
                memberOauthEntity.setMemberId(memberEntity.getId());
                memberOauth.save(memberOauthEntity);

            } else {
                memberEntity = this.member.entity(memberOauthEntity.getMemberId());
            }

            String token = UUID.randomUUID().toString().replaceAll("-", "");
            memberEntity.setAuthToken(token);
            memberEntity.setLastLogin(new Timestamp(System.currentTimeMillis()));
            memberEntity.setLastIp(RequestUtil.getClientIp(request));
            member.save(memberEntity);
            member.refreshSession(memberEntity);
            return memberEntity;

        }
        return null;
    }

    @PostMapping("sendCode")
    public void sendCode(@RequestBody Map<String, String> map, HttpServletRequest request) throws SQLException {
        Random rad = new Random();
        String code = String.format("%06d", rad.nextInt(1000000));
        String mobile = map.get("mobile");

        try {
            SmsUtil.sendLoginSms(mobile, code);
        } catch (ClientException e) {
            logger.error(e.getMessage(), e);
            throw new ValidateException(e.getErrMsg());
        }


        SmsLoginEntity smsLoginEntity = new SmsLoginEntity();
        smsLoginEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
        smsLoginEntity.setCode(code);
        smsLoginEntity.setMobile(mobile);
        smsLoginEntity.setInUse(false);
        smsLoginEntity.setClientIp(RequestUtil.getClientIp(request));
        smsLogin.save(smsLoginEntity);
    }

    @PostMapping("inputInviteCode")
    @AuthLogin
    public void inputInviteCode(@RequestBody Map<String, String> map) throws SQLException {


        //先判断邀请码有没有被使用
        String code = map.get("code");
        if (Strings.isNullOrEmpty(code)) {
            throw new ValidateException("邀请码不能为空");
        }

        //反解邀请码
        Long id = SerialCodeGen.codeToId(code);
        InviteCodeEntity inviteCodeEntity = inviteCode.entity(id);
        if (inviteCodeEntity == null) {
            throw new ValidateException("非法邀请码");
        }

        boolean inUse = inviteCodeEntity.getInUse();
        if (inUse) {
            throw new ValidateException("邀请码已经使用");
        }

        MemberEntity inviteMemberEntity = member.entity(inviteCodeEntity.getMemberId());
        if (inviteMemberEntity == null) {
            throw new ValidateException("该邀请码用户已经不存在");
        }

        MemberEntity entity = member.entity(RequestContext.getMemberId());
        if(entity == null){
            throw new ValidateException("用户"+ RequestContext.getMemberId() + "不存在");
        }
        entity.setParentId(inviteMemberEntity.getId());
        entity.setInviteCode(code);
        member.save(entity);

        inviteCodeEntity.setInUse(true);
        inviteCodeEntity.setUseMemberId(RequestContext.getMemberId());
        inviteCodeEntity.setUseTime(new Timestamp(System.currentTimeMillis()));
        inviteCode.save(inviteCodeEntity);
    }

    @GetMapping("genInviteCode")
    public GenInviteCodeModel genInviteCode() throws SQLException {
        MemberEntity entity = member.entity(RequestContext.getMemberId());
        Long used = inviteCode.used(entity.getId());
        Long total = inviteCode.total(entity.getId());
        if (total == 0) {
            insertInviteCode(RequestContext.getMemberId());
        }
        InviteCodeEntity inviteCodeEntity = inviteCode.top(entity.getId());


        String code = "";
        if (inviteCodeEntity != null) {
            code = inviteCodeEntity.getCode();
        }

        GenInviteCodeModel model = new GenInviteCodeModel();
        model.setCode(code);
        model.setUsed(used);
        model.setTotal(total);
        return model;


    }

    @GetMapping("sessions")
    @JsonBody(false)
    public Map<String, MemberSession> sessions() {
        return member.sessions();
    }


    @GetMapping("info")
    @AuthLogin
    public MemberEntity info() throws SQLException {
        MemberEntity entity = member.entity(RequestContext.getMemberId());
        if (entity == null) {
            throw new UnauthorizedException("未登录");
        }
        if (!Strings.isNullOrEmpty(entity.getHeadPic())) {
            entity.setHeadPic(imageDomain + entity.getHeadPic());
        }
        return entity;
    }

    @PostMapping("save")
    @AuthLogin
    public void save(@RequestBody MemberEntity entity) throws SQLException {
        if (entity.getId() == null || entity.getId() == 0) {
            entity.setId(RequestContext.getMemberId());
        }

        if (!entity.getId().equals(RequestContext.getMemberId())) {
            throw new ValidateException("非法操作");
        }

        //余额等不能修改
        entity.setBalance(null);
        entity.setBalanceEncryt(null);
        entity.setLevel(null);

        member.save(entity);
    }

    @GetMapping("statistic")
    @AuthLogin
    public StatisticModel  statistic() throws SQLException {
         Long memberId = RequestContext.getMemberId();
         StatisticModel model = new StatisticModel();
         model.setTodaySales(order.todaySales(memberId));
         model.setCurrentMonthSales(order.currentMonthSales(memberId));
         model.setLastMonthSales(order.lastMonthSalse(memberId));
         model.setTodayAgency(order.todaySalesAgency(memberId));
         model.setCurrentMonthAgency(order.currentMonthAgency(memberId));
         model.setLastMonthAgency(order.lastMonthAgency(memberId));
         return model;
    }

}
